#include "alarm_view.h"
#include "ui_alarm_view.h"
#include <QDebug>
#include "dealer_handler.h"
#include <QJsonDocument>
#include <QJsonArray>
#include <QJsonObject>
#include <QDateTime>
#include "search_tree_widget.h"
#include <QVBoxLayout>
#include "database_manager.h"

AlarmView::AlarmView(SearchTreeWidget *search_tree, QWidget *parent)
    : QWidget(parent),                              // 父窗口
      ui_(new Ui::AlarmView),                       // 界面
      search_tree_(search_tree),                    // 搜索树
      dealer_handler_(DealerHandler::getInstance()) // 网络处理类
{
    ui_->setupUi(this);

    // 初始化表格
    initTableWidget(ui_->tableWidget_all);
    initTableWidget(ui_->tableWidget_hint);
    initTableWidget(ui_->tableWidget_notice);
    initTableWidget(ui_->tableWidget_alarm);
    initTableWidget(ui_->tableWidget_ungency);

    // 替换原有的树形控件
    QVBoxLayout *layout = new QVBoxLayout(ui_->leftContainer);
    layout->setContentsMargins(0, 0, 0, 0);

    // 连接tab切换信号
    connect(ui_->tabWidget, &QTabWidget::currentChanged, this, &AlarmView::onTabChanged);

    // 连接网络消息接收信号
    connect(dealer_handler_, &DealerHandler::messageReceived, this, &AlarmView::onNetworkMessageReceived);

    connect(search_tree_, &SearchTreeWidget::itemClicked, this, &AlarmView::onSearchTreeWidgetItemClicked);
}

AlarmView::~AlarmView()
{
    delete ui_;
}

void AlarmView::onTabChanged(int index)
{
    // 根据不同的tab索引处理不同的告警类型
    switch (index)
    {
    case 0: // 全部
        qDebug() << "切换到全部告警";
        break;
    case 1: // 提示
        qDebug() << "切换到提示告警";
        break;
    case 2: // 注意
        qDebug() << "切换到注意告警";
        break;
    case 3: // 告警
        qDebug() << "切换到告警";
        break;
    case 4: // 紧急
        qDebug() << "切换到紧急告警";
        break;
    default:
        break;
    }
}

void AlarmView::initAlarmList()
{
    dealer_handler_->sendRequest("get-alarm-record", "100");
}

void AlarmView::onNetworkMessageReceived(const QString &method, const QString &body)
{
    if (method == "get-alarm-record")
    {
        // 解析JSON数据
        QJsonDocument doc = QJsonDocument::fromJson(body.toUtf8());
        if (!doc.isArray())
        {
            qDebug() << "Invalid JSON data format";
            return;
        }

        QJsonArray array = doc.array();
        for (const QJsonValue value : array)
        {
            if (!value.isObject())
                continue;

            QJsonObject alarmData = value.toObject();

            int64_t id = alarmData["id"].toInt();
            int status = alarmData["status"].toInt();
            int64_t point_id = alarmData["pointId"].toInt();
            int point_address = alarmData["pointAddress"].toInt();
            double max_threshold = alarmData["maxThreshold"].toDouble();
            int64_t create_at = alarmData["createdAt"].toVariant().toLongLong();
            int64_t update_at = alarmData["updatedAt"].toVariant().toLongLong();
            int64_t substation_id = alarmData["substation"].toObject()["id"].toInt();
            QString substation_desc = alarmData["substation"].toObject()["description"].toString();
            int64_t alarm_rule_id = alarmData["alarmRule"].toObject()["id"].toInt();
            int interval_secs = alarmData["alarmRule"].toObject()["intervalSeconds"].toInt();
            double threshold_value = alarmData["alarmRule"].toObject()["threshold"].toDouble();
            MetricTypeEnum metric_type = static_cast<MetricTypeEnum>(alarmData["alarmRule"].toObject()["metricTypeIndex"].toInt());
            ThresholdUnitEnum threshold_unit = static_cast<ThresholdUnitEnum>(alarmData["alarmRule"].toObject()["thresholdUnitIndex"].toInt());
            AlarmLevelEnum alarm_level = static_cast<AlarmLevelEnum>(alarmData["alarmRule"].toObject()["alarmLevelIndex"].toInt());

            this->appendAlarmRecord(id, status, alarm_rule_id, substation_id, substation_desc, point_id, point_address, max_threshold, create_at, update_at,
                                    interval_secs, threshold_value, metric_type, threshold_unit, alarm_level);
        }

        // 渲染告警表格
        renderAlarmTable();
    }
    if (method == "append-alarm-record")
    {
        // 解析JSON数据
        QJsonDocument doc = QJsonDocument::fromJson(body.toUtf8());
        if (!doc.isArray())
        {
            qDebug() << "Invalid JSON data format";
            return;
        }

        QJsonArray array = doc.array();
        for (const QJsonValue value : array)
        {
            if (!value.isObject())
                continue;

            QJsonObject alarmData = value.toObject();

            int64_t id = alarmData["id"].toInt();
            int status = alarmData["status"].toInt();
            int64_t point_id = alarmData["pointId"].toInt();
            int point_address = alarmData["pointAddress"].toInt();
            double max_threshold = alarmData["maxThreshold"].toDouble();
            int64_t create_at = alarmData["createdAt"].toVariant().toLongLong();
            int64_t update_at = alarmData["updatedAt"].toVariant().toLongLong();
            int64_t substation_id = alarmData["substation"].toObject()["id"].toInt();
            QString substation_desc = alarmData["substation"].toObject()["description"].toString();
            int64_t alarm_rule_id = alarmData["alarmRule"].toObject()["id"].toInt();
            int interval_secs = alarmData["alarmRule"].toObject()["intervalSeconds"].toInt();
            double threshold_value = alarmData["alarmRule"].toObject()["threshold"].toDouble();
            MetricTypeEnum metric_type = static_cast<MetricTypeEnum>(alarmData["alarmRule"].toObject()["metricTypeIndex"].toInt());
            ThresholdUnitEnum threshold_unit = static_cast<ThresholdUnitEnum>(alarmData["alarmRule"].toObject()["thresholdUnitIndex"].toInt());
            AlarmLevelEnum alarm_level = static_cast<AlarmLevelEnum>(alarmData["alarmRule"].toObject()["alarmLevelIndex"].toInt());

            this->appendAlarmRecord(id, status, alarm_rule_id, substation_id, substation_desc, point_id, point_address, max_threshold, create_at, update_at,
                                    interval_secs, threshold_value, metric_type, threshold_unit, alarm_level);
        }
        // 渲染告警表格
        renderAlarmTable();
    }
}

void AlarmView::addAlarmRecord(QTableWidget *table, AlarmRecord *alarm_record)
{
    int row = table->rowCount();
    table->insertRow(row);

    // 子站描述
    QString description = alarm_record->state_info()->description();
    QTableWidgetItem *descItem = new QTableWidgetItem(description);
    table->setItem(row, 0, descItem);

    // 状态
    int status = alarm_record->status();
    QTableWidgetItem *statusItem = new QTableWidgetItem(status == 0 ? "历史告警" : "告警中");
    statusItem->setForeground(status == 0 ? QColor("#2196F3") : QColor("#F44336"));
    table->setItem(row, 1, statusItem);

    // 告警规则
    AlarmRule *alarm_rule = alarm_record->alarm_rule();
    int metricType = static_cast<int>(alarm_rule->metricType());
    int intervalSeconds = alarm_rule->intervalSecs();

    QString ruleText;
    switch (metricType)
    {
    case MetricTypeEnum::CONTROL_FRAME_TOTAL:
        ruleText = QString("%1秒内控制帧总数越限").arg(intervalSeconds);
        break;
    case MetricTypeEnum::CONTROL_POINT_TOTAL:
        ruleText = QString("%1秒内控制点总数越限").arg(intervalSeconds);
        break;
    case MetricTypeEnum::SAME_YK_POINT:
    {
        QVector<PointInfo> point_list = DatabaseManager::queryPoints(alarm_record->substation_id(), static_cast<int>(PointInfo::Type::YK));
        QString yk_point_desc = "";
        for (const PointInfo &point : point_list)
        {
            if (point.point_id == alarm_record->point_address())
            {
                yk_point_desc = point.point_desc;
            }
        }
        ruleText = QString("%1秒内多次遥控相同地址%2越限").arg(intervalSeconds).arg(yk_point_desc);
    }
        break;
    case MetricTypeEnum::SAME_SD_POINT:
    {
        QVector<PointInfo> point_list = DatabaseManager::queryPoints(alarm_record->substation_id(), static_cast<int>(PointInfo::Type::YT));
        QString sd_point_desc = "";
        for (const PointInfo &point : point_list)
        {
            if (point.point_id == alarm_record->point_address())
            {
                sd_point_desc = point.point_desc;
            }
        }
        ruleText = QString("%1秒内多次设值相同地址%2越限").arg(intervalSeconds).arg(sd_point_desc);
    }
        break;
    case MetricTypeEnum::YT_PRECISION:
    {
        QVector<PointInfo> point_list = DatabaseManager::queryPoints(alarm_record->substation_id(), static_cast<int>(PointInfo::Type::YT));
        QString yt_point_desc = "";
        for (const PointInfo &point : point_list)
        {
            if (point.point_id == alarm_record->point_address())
            {
                yt_point_desc = point.point_desc;
            }
        }
        QString yc_point_desc = "";
        auto grab_address = DatabaseManager::queryPointGrab(alarm_record->substation_id(), alarm_record->point_address());
        point_list = DatabaseManager::queryPoints(alarm_record->substation_id(), static_cast<int>(PointInfo::Type::YC));
        for (const PointInfo &point : point_list)
        {
            if (point.point_id == grab_address)
            {
                yc_point_desc = point.point_desc;
            }
        }

        ruleText = QString("%1秒内设点%2的目标值与关联遥测点%3的值相差")
                       .arg(intervalSeconds)
                       .arg(yt_point_desc)
                       .arg(yc_point_desc);
    }
    break;
    case MetricTypeEnum::YC_SLOPE:
    {
        QVector<PointInfo> point_list = DatabaseManager::queryPoints(alarm_record->substation_id(), static_cast<int>(PointInfo::Type::YC));
        QString yc_point_desc = "";
        for (const PointInfo &point : point_list)
        {
            if (point.point_id == alarm_record->point_address())
            {
                yc_point_desc = point.point_desc;
            }
        }
        ruleText = QString("%1秒内%2遥测值跳变越限").arg(intervalSeconds).arg(yc_point_desc);
    }
        break;
    default:
        ruleText = "未知告警规则";
        break;
    }

    QTableWidgetItem *ruleItem = new QTableWidgetItem(ruleText);
    table->setItem(row, 2, ruleItem);

    // 越上限值
    double threshold = alarm_rule->thresholdValue();
    ThresholdUnitEnum threshold_unit = alarm_rule->thresholdUnit();
    QTableWidgetItem *thresholdItem = nullptr;
    if (threshold_unit == ThresholdUnitEnum::PERCENT)
    {
        thresholdItem = new QTableWidgetItem(QString::number(threshold) + "%");
    }
    else
    {
        thresholdItem = new QTableWidgetItem(QString::number(threshold));
    }
    table->setItem(row, 3, thresholdItem);

    // 最大越限值
    double maxThreshold = alarm_record->max_threshold();
    QTableWidgetItem *maxThresholdItem = nullptr;
    if (threshold_unit == ThresholdUnitEnum::PERCENT)
    {
        maxThresholdItem = new QTableWidgetItem(QString::number(maxThreshold * 100) + "%");
    }
    else
    {
        maxThresholdItem = new QTableWidgetItem(QString::number(maxThreshold));
    }
    table->setItem(row, 4, maxThresholdItem);

    // 告警等级
    QString levelText = AlarmRule::getAlarmLevelText(alarm_rule->alarmLevel());
    QTableWidgetItem *levelItem = new QTableWidgetItem(levelText);
    table->setItem(row, 5, levelItem);

    // 告警产生时间
    qint64 createdAt = alarm_record->create_at();
    QDateTime createTime = QDateTime::fromMSecsSinceEpoch(createdAt);
    QTableWidgetItem *createItem = new QTableWidgetItem(createTime.toString("yyyy-MM-dd hh:mm:ss"));
    table->setItem(row, 6, createItem);

    // 最后更新时间
    qint64 updatedAt = alarm_record->update_at();
    QDateTime updateTime = QDateTime::fromMSecsSinceEpoch(updatedAt);
    QTableWidgetItem *updateItem = new QTableWidgetItem(updateTime.toString("yyyy-MM-dd hh:mm:ss"));
    table->setItem(row, 7, updateItem);
}

void AlarmView::clearAllTables()
{
    ui_->tableWidget_all->setRowCount(0);
    ui_->tableWidget_hint->setRowCount(0);
    ui_->tableWidget_notice->setRowCount(0);
    ui_->tableWidget_alarm->setRowCount(0);
    ui_->tableWidget_ungency->setRowCount(0);
}

void AlarmView::initTableWidget(QTableWidget *table)
{
    // 设置表格属性
    table->setEditTriggers(QAbstractItemView::NoEditTriggers);                 // 禁止编辑
    table->setSelectionBehavior(QAbstractItemView::SelectRows);                // 整行选择
    table->setSelectionMode(QAbstractItemView::SingleSelection);               // 只能选择一行
    table->horizontalHeader()->setStretchLastSection(false);                   // 最后一列不自动拉伸
    table->horizontalHeader()->setSectionResizeMode(QHeaderView::Interactive); // 允许手动调整列宽
    table->verticalHeader()->setVisible(false);                                // 隐藏行号
    table->setShowGrid(true);                                                  // 显示网格线
    table->setAlternatingRowColors(true);                                      // 交替行颜色

    // 设置列宽
    table->setColumnWidth(0, 120);                                            // 子站描述
    table->setColumnWidth(1, 80);                                             // 状态
    table->horizontalHeader()->setSectionResizeMode(2, QHeaderView::Stretch); // 告警规则（弹性布局）
    table->setColumnWidth(3, 80);                                             // 越上限值
    table->setColumnWidth(4, 100);                                            // 最大越限值
    table->setColumnWidth(5, 60);                                             // 告警等级
    table->setColumnWidth(6, 150);                                            // 告警产生时间
    table->setColumnWidth(7, 150);                                            // 最后更新时间
}

void AlarmView::showEvent(QShowEvent *event)
{
    QWidget::showEvent(event);
    // 每次显示时初始化告警列表
    initAlarmList();
    // 设置搜索树形控件
    search_tree_->selectRootNode();
    search_tree_->setContextMenuEnabled(false);
    search_tree_->setShortcutEnabled(false);
    search_tree_->setDoubleClickEnabled(false);
    ui_->leftContainer->layout()->addWidget(search_tree_);

    if (state_info_.id() != 0)
    {
        search_tree_->selectNodeByStateInfo(&state_info_);
    }
}

int AlarmView::appendAlarmRecord(int64_t id, int status, int64_t alarm_rule_id, int64_t substation_id, QString substation_desc,
                                 int64_t point_id, int point_address, double max_threshold, int64_t create_at, int64_t update_at,
                                 int interval_secs, double threshold_value, MetricTypeEnum metric_type, ThresholdUnitEnum threshold_unit, AlarmLevelEnum alarm_level)
{
    // 创建告警记录
    AlarmRecord *alarm_record = new AlarmRecord(id, status, alarm_rule_id, substation_id, point_id, max_threshold, create_at, update_at);
    alarm_record->set_point_address(point_address);
    // 创建告警规则
    AlarmRule *alarm_rule = new AlarmRule(metric_type, alarm_level, threshold_unit, substation_id);
    alarm_rule->setIntervalSecs(interval_secs);
    alarm_rule->setThresholdValue(threshold_value);
    alarm_record->set_alarm_rule(alarm_rule);

    // 创建变电站信息
    StateInfo *state_info = new StateInfo(substation_id, 0, substation_desc, substation_desc);
    alarm_record->set_state_info(state_info);

    // 遍历alarm_record_vec_，根据id查找，如果不存在则insert，如果存在则更新
    for (int i = 0; i < alarm_record_vec_.size(); i++)
    {
        if (alarm_record_vec_[i]->id() == id)
        {
            alarm_record_vec_[i] = alarm_record;
            return i;
        }
    }
    // 创建主站信息
    alarm_record_vec_.prepend(alarm_record);
    // 如果alarm_record_vec_大小为1000，则删除最早的告警记录
    if (alarm_record_vec_.size() > 1000)
    {
        delete alarm_record_vec_.last();
        alarm_record_vec_.removeLast();
    }
    return alarm_record_vec_.size();
}

void AlarmView::renderAlarmTable()
{
    // 清空所有表格
    clearAllTables();

    // 遍历所有告警记录
    for (int i = 0; i < alarm_record_vec_.size(); i++)
    {
        AlarmRecord *alarm_record = alarm_record_vec_[i];
        AlarmRule *alarm_rule = alarm_record->alarm_rule();
        if(state_info_.isRtu() && alarm_record->substation_id() != state_info_.id())
        {
            continue;
        }

        // 根据告警级别添加到对应的表格
        switch (alarm_rule->alarmLevel())
        {
        case AlarmLevelEnum::ALERT:
            addAlarmRecord(ui_->tableWidget_hint, alarm_record);
            break;
        case AlarmLevelEnum::NOTICE:
            addAlarmRecord(ui_->tableWidget_notice, alarm_record);
            break;
        case AlarmLevelEnum::ATTENTION:
            addAlarmRecord(ui_->tableWidget_alarm, alarm_record);
            break;
        case AlarmLevelEnum::CRITICAL:
            addAlarmRecord(ui_->tableWidget_ungency, alarm_record);
            break;
        default:
            break;
        }

        // 所有告警都添加到全部告警表格
        addAlarmRecord(ui_->tableWidget_all, alarm_record);
    }
}

void AlarmView::onSearchTreeWidgetItemClicked(StateInfo state_info)
{
    this->state_info_ = state_info;
    renderAlarmTable();
}
